package model;

import java.util.ArrayList;
import java.util.Map;

/**
 * This class is responsibile för handling the logic in the system it holds user, case and event data.
 *
 * @author Kevin
 */
public class MiljoBoven
{

    private final FileManager fm;

    private ArrayList<User> userlist;
    private ArrayList<Cases> caselist;
    private User currentUser; // User currrently using the system
    private Cases currentCase; // Case currently being edited
    private final String USERS_FILENAME = "unitTestUsers.dat";
    private final String CASES_FILENAME = "unitTestCases.dat";

    /**
     * Constructor for the class
     */
    public MiljoBoven()
    {
        fm = new FileManager();
        userlist = (ArrayList<User>) fm.readFile(USERS_FILENAME);
        caselist = (ArrayList<Cases>) fm.readFile(CASES_FILENAME);
    }

    /**
     * Sets the right table data for specifik user
     *
     * @return
     */
    public String[][] setTableRowData()
    {
        ArrayList<String[]> tableData = new ArrayList<>();

        switch (currentUser.getUserType())
        {
            case COORDINATOR:
                for (Cases thisCase : caselist)
                {
                    tableData.add(getCaseData(thisCase));
                }
                break;
            case MANAGER:
                for (Cases thisCase : caselist)
                {
                    if (thisCase.getDepartment() == currentUser.getDepartment())
                    {
                        tableData.add(getCaseData(thisCase));
                    }
                }
                break;
            case ADMINISTRATOR:
                for (Cases thisCase : caselist)
                {
                    if (thisCase.getRespAdministrator().getUsername().equals(currentUser.getUsername()))
                    {
                        System.out.println("Admin match");
                        tableData.add(getCaseData(thisCase));
                    }
                }
                break;
        }
        return tableData.toArray(new String[0][0]);
    }

    /**
     * Translates case data to strings
     *
     * @param thisCase the case we currently getting data from
     * @return array of Strings
     */
    private String[] getCaseData(Cases thisCase)
    {
        String id = String.valueOf(thisCase.getiD());
        String name = String.valueOf(thisCase.getCaseName());
        String department = String.valueOf(thisCase.getDepartment());
        String date = String.valueOf(thisCase.getReportDate());
        String status = String.valueOf(thisCase.getStatus());
        String administrator = String.valueOf(thisCase.getRespAdministrator());
        String type = String.valueOf(thisCase.getCrimeType());
        String[] adminRow
                =
                {
                    id, name, department, date, status, administrator, type
                };
        return adminRow;
    }

    /**
     * Gets the last created case
     *
     * @return
     */
    public String[] getNewCase()
    {
        int lastIndex = caselist.size() - 1;

        caselist.get(lastIndex);

        return getCaseData(caselist.get(lastIndex));
    }

    public void createNewCase()
    {
        currentCase = new Cases();
    }

    /**
     * updates case
     *
     * @param caseData to be updated
     * @return case data
     */
    public boolean updateCase(Map caseData)
    {
        if (currentCase == null)
        {
            currentCase = new Cases();
        }
        return currentCase.setData(caseData);
    }

    /**
     * Matching the entered username to a username in the userlist
     *
     * @param enteredUserName username from username field, loginPanel
     * @return if enteredUser is match it will return the user else null
     */
    private User getUserByUsername(String enteredUserName)
    {
        for (User userInList : userlist)
        {
            if (userInList.getUsername().equals(enteredUserName))
            {
                return userInList;
            }

        }
        return null;
    }

    /**
     * Checks if the password matches the stored password
     *
     * @param enteredUsername username entered by user
     * @param enteredPassword passwrd entered by user
     * @return true if the password matches else it will return false
     */
    public boolean checkPassword(String enteredUsername, String enteredPassword)
    {
        User user = getUserByUsername(enteredUsername);
        return (user != null && user.getPassword().equals(enteredPassword));
    }

    /**
     * Saves the userlist to a file
     *
     * @param userList
     * @param filename
     */
    public void saveUserList(ArrayList<Object> userList, String filename)
    {
        fm.writeToFile(userList, filename);
    }

    /**
     * Sets logged in user as current user
     *
     * @param user user who logged in
     */
    public void setCurrentUser(String user)
    {
        this.currentUser = getUserByUsername(user);
    }

    public User getCurrentUser()
    {
        return currentUser;
    }

    public ArrayList<Cases> getCaselist()
    {
        return caselist;
    }

    public ArrayList<Event> getEventsForCase()
    {
        if (currentCase == null)
        {
            return new ArrayList<>();
        }
        return currentCase.getEvents();
    }

    /**
     * Returns a list of all users in a specified department.
     *
     * @param department
     * @return An ArrayList containing Users of the department. If no department is specified, returns a list of all
     * users.
     */
    public ArrayList<User> getAdministratorsByDepartment(Department department)
    {

        if (department != null)
        {
            ArrayList<User> departmentAdministrators = new ArrayList<>();
            for (User user : userlist)
            {
                if (user.getDepartment() == department && user.getUserType() == User.Type.ADMINISTRATOR)
                {
                    departmentAdministrators.add(user);
                }
            }
            return departmentAdministrators;
        }
        else
        {
            return userlist;
        }
    }

    public Cases getCurrentCase()
    {
        return currentCase;
    }

    public void setCurrentCase(Cases currentCase)
    {
        this.currentCase = currentCase;
    }

    /**
     * Adds an event to the list of current case events
     *
     * @param newEvent The event to be added
     */
    public void addEvent(Event newEvent)
    {
        if (currentCase == null)
        {
            currentCase = new Cases();
        }
        getEventsForCase().add(newEvent);
    }

    /**
     * Adds a case to the list of cases
     *
     */
    public void addCurrentCase()
    {
        if (currentCase != null && !caselist.contains(currentCase))
        {
            caselist.add(currentCase);
        }
    }

    /**
     * Returns the case with the specified caseID
     *
     * @param id The id of the case to be returned
     * @return Case with specified id
     */
    public Cases getCaseById(int id)
    {
        for (Cases aCase : caselist)
        {
            if (aCase.getiD() == id)
            {
                return aCase;
            }
        }
        return null;
    }

    /**
     * Saves all cases to a file
     *
     * @return true if successful, false otherwise
     */
    public boolean saveCases()
    {
        return fm.writeToFile(caselist, CASES_FILENAME);
    }

}
